<template>
  <div
    v-loading="isVisualVappShowLoadingProgress && isLoading"
    :class="`rc-button ${visualThemeClassName} ${config.config.property.componentStyle}-Style`"
    :style="getCssStyle('grid')"
  >
    <Tooltip ref="Tooltip" :component-style="config.config.property.componentStyle" />
    <AdvancedLinkageToolbar :wid="widgetInstanceId" :config="config" />
    <div :class="`btns ${justify}`">
      <div :style="getSelectStyle()">
        <el-input
          v-show="type === 'kaidu'"
          v-model.number="ratio"
          type="number"
          class="ratio-input"
          max="100"
          min="0"
          :disabled="isDesignView"
          :style="getInputStyleVar()"
        >
          <template #append>%</template>
        </el-input>
        <el-select
          v-show="type === 'speedControl'"
          ref="defSelect"
          v-model="selectVal"
          :popper-append-to-body="true"
          :class="`select-box-select select-box-select-${componentStyle}`"
          :popper-class="`select-component-popper-${componentStyle} select-poper1-${componentStyle}`"
          clearable
          filterable
          :collapse-tags="true"
          size="default"
          :placeholder="$demoi18n('view.select.placeholder')"
          :no-data-text="$demoi18n('message.noData')"
        >
          <el-option
            v-for="(item, index) in data"
            :key="index"
            :class="`select-box-select-option select-box-select-option-${componentStyle}`"
            :label="item.name"
            :value="item.status"
          ></el-option>
        </el-select>
      </div>
      <span
        v-for="(btn, i) in buttons"
        :key="i"
        v-visual-tooltip="getTooltip(btn)"
        class="btn"
        :style="getBtnStyle(i)"
        @click="clickBtn(i)"
      >
        <span class="btn_inner">{{ name }}</span>
      </span>
    </div>
  </div>
</template>
<script>
import STATIC_DATA from '@/common/staticData';
import AdvancedLinkageToolbar from '@/components/common/advanced-linkage/advanced-linkage-toolbar.vue';
import chartBase from '@/mixin/chart-base.js';
import emitComponentBase from '@/mixin/emit-component-base.js';
import dataModel from '@/models/panel-config-data.js';
import { convertValue, isEmpty } from '@/utils/util.js';
import Tooltip from '../common/tooltip/tooltip.vue';
import config from './config/config';
import dfCssStyle from './config/cssStyle-default.js';
import {
  bus,
  defaultPwdRules,
  rcEquimentObjModelCode,
  rcLogObjModelCode,
  requestFailure,
  secondLoginFailure,
  tipCancel,
} from './config/valid.js';

export default {
  name: 'RemoteControlButton',
  components: { Tooltip, AdvancedLinkageToolbar },
  mixins: [chartBase, emitComponentBase],
  props: ['pareentId', 'widgetId', 'isDesignView', 'widgetInstanceId', 'widgetName', 'identifier', 'layout', 'w', 'h'],
  data() {
    const _config = JSON.parse(JSON.stringify(config));
    return {
      ..._config.config.property,
      dfCssStyle,
      activeBtn: {},
      isLoading: false,
      ratio: 0,
      isDev: process.env.NODE_ENV === 'development',
      selectVal: '',
      selectContentOptions: [],
    };
  },
  computed: {
    showRatioInput() {
      return this.type === 'kaidu';
    },
  },
  watch: {
    selectContentOptions() {
      this.selectContentOptionsChanged();
    },
  },
  created() {
    this.orgConfig = config;
    this.config = JSON.parse(JSON.stringify(this.orgConfig));
    bus.$on(`changeControlType_${this.widgetInstanceId}`, this.switchControlType);
  },
  methods: {
    selectContentOptionsChanged() {
      this.selectVal = '';
    },
    loadWidget(pageStatus) {
      this.updateConfigProperty();
      if (this.isDev || this.emitComponentStatus) {
        !this.isRealTime && this.debounceGetData();
      }
      this.afterLoadWidget();
    },
    getChartData() {
      const { data } = this.config.config;
      const { property } = this.config.config;
      let { tableData = [] } = data;
      if (data.dataSourceType === 'staticData') {
        tableData = this.getStaticData();
      }
      this.type = property.type;
      this.selectContentOptions = property.data;
      this.sendDataToConfig(tableData);
    },
    updateRatio() {
      const { tableData = [] } = this.config.config.data;
      const data = tableData.find(item => item.type === true) || {};
      const { value = '' } = data;
      this.ratio = parseInt(value) || 0;
      if (this.type === 'speedControl') {
        this.selectVal = value;
      }
    },
    updateConfigProperty() {
      const { property } = this.config.config;
      Object.keys(property || {}).forEach(i => {
        this[i] = property[i];
      });
      this.updateRatio();
    },
    getSelectStyle() {
      if (this.type === 'qiting') {
        return {};
      }
      return {
        'margin-bottom': `${this.distance}px`,
        'margin-right': `${this.distance}px`,
      };
    },
    getBtnStyle(i) {
      const commonStyle = this.getCssStyle('allBtn');
      commonStyle.padding = `0 ${convertValue(15, 0, 'w')}px`;

      const { cssStyle = {} } = this.buttons[i];
      const selfStyle = this.getCssStyle(cssStyle.btn || {});

      // 激活状态
      let activeStyle = {}; // 公共计划样式
      let selfActiveStyle = {}; // 自身激活样式
      if (this.buttons[i] === this.activeBtn) {
        activeStyle = this.getCssStyle('allBtn_actived');
        selfActiveStyle = this.getCssStyle(cssStyle.btn_actived || {});
      }

      const style = {
        ...commonStyle,
        ...selfStyle,
        ...activeStyle,
        ...selfActiveStyle,
      };
      return style;
    },

    getInputStyleVar() {
      const btnInputStyle = this.getCssStyle('btnInput');
      return {
        '--bgColor': btnInputStyle.backgroundColor?.replace('!important', ''),
        '--brColor': btnInputStyle.borderColor,
        '--textColor': btnInputStyle.textColor,
      };
    },
    clickBtn(i) {
      const btn = this.buttons[i];
      this.activeBtn = btn;
      this.executeAction('', btn);

      if (this.isDesignView) {
        return;
      }
      this.handlerBtnClick();
    },
    handlerBtnClick() {
      this.showTip()
        .then(pwd => {
          // 点击确定
          const { verifyType = 'password' } = this.config.config.property;
          if (verifyType !== 'password') {
            // 没有开启密码验证跳过验证
            return Promise.resolve(pwd);
          }

          // 获取平台密码规则 => 本地验证 => 二次登录 => 更新api数据 => 增加一条操作记录
          return this.getValidators()
            .catch(_ =>

              // 获取平台密码校验规则失败，使用默认的
              Promise.resolve({ rule: defaultPwdRules }),
            )
            .then(rules =>

              // 本地验证密码是否符合规则
              this.validRules(rules, pwd),
            )
            .then(_ => {
              // 二次登录
              const url = this.getSecondLoginUrl();
              return this.secondLogin(pwd, url);
            })
            .catch(err =>

              // 本地验证失败或者二次登录失败，回调失败
              Promise.reject(err),
            );
        })

        // 更新xminer对象模型数据，无论是否成功都增加一条接口调用接口
        .then(res => this.updateData().then(this.addRCAccessRecord, this.addRCAccessRecord))
        .catch(err => {
          if (err.type === 'error') {
            this.$message.error(err.message);
          } else {
            this.$message.info(err.message);
          }
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    showTip() {
      return new Promise((resolve, reject) => {
        const { componentStyle, verifyType = 'password' } = this.config.config.property;
        const customClass = `visualComponents_theme_message_${componentStyle}`;
        let tipContent = '当前将远程控制设备, 请确认是否继续操作';
        const title = '请确认';
        const options = {
          confirmButtonText: this.$demoi18n('btn.confirm'),
          cancelButtonText: this.$demoi18n('btn.cancel'),
          customClass: customClass,
          type: 'warning',
        };
        if (verifyType === 'password') {
          tipContent = '当前将远程控制设备, 请输入您的登录密码验证身份!';
          options.inputType = 'password';
          options.inputValidator = value => {
            if (!value) {
              return '登录密码不能为空';
            }
            return true;
          };
          this.$prompt(tipContent, title, options)
            .then(({ value }) => {
              resolve(value);
            })
            .catch(err => {
              reject(tipCancel);
            });
        } else {
          this.$confirm(tipContent, title, options)
            .then(({ value }) => {
              resolve(value);
            })
            .catch(err => {
              reject(tipCancel);
            });
        }
      });
    },
    getValidators() {
      return new Promise((resolve, reject) => {
        this.isLoading = true;
        window
          ._UIDesingerAxios({
            method: 'get',
            url: '/iam/uc/v1/validators',
          })
          .then(res => {
            const rules = (res.data && res.data.data && res.data.data.password) || {};
            if (isEmpty(rules)) {
              reject(requestFailure);
            } else {
              resolve(rules);
            }
          })
          .catch(err => {
            reject(requestFailure);
          });
      });
    },
    validRules(rules, pwd) {
      const { maxLength = 32, message = '密码不符合规则', minLength = 8, rule } = rules;
      const error = { type: 'error', message: message };

      let valid = pwd.length >= minLength && pwd.length <= maxLength;
      if (!valid) {
        return Promise.reject(error);
      }

      valid = new RegExp(rule).test(pwd);
      if (!valid) {
        return Promise.reject(error);
      }
      return Promise.resolve(pwd);
    },
    secondLogin(pwd, url) {
      return new Promise((resolve, reject) => {
        window
          ._UIDesingerAxios({
            method: 'post',
            url: '/auth/second/login',
            data: {
              password: pwd,
              url: url,
            },
          })
          .then(res => {
            const success = (res.data && res.data.success) || false;
            success ? resolve(res) : reject(secondLoginFailure);
          })
          .catch(err => {
            reject(requestFailure);
          });
      });
    },
    getSecondLoginUrl() {
      const { dataSourceType, tableData = [] } = this.config.config.data;
      let url = '';
      if (dataSourceType === 'xMiner') {
        const [first = {}] = tableData;
        const { id = '' } = first;
        url = `POST-/dcp/data/data/v3/${rcEquimentObjModelCode}/update`;
      } else if (dataSourceType === 'fabric') {
        url = 'POST-/api-manager/api/v1/flatten/exchange';
      } else {
      }
      return url;
    },

    // 添加一条访问记录
    addRCAccessRecord(updateDataResult) {
      const dataSourceType = 'xMiner';
      const method = `addAObjModelRecord${dataSourceType}`;
      const { user = {} } = window._adoPremise;
      const { name = '', aliasName = '' } = user;
      const { widgetInstanceId } = this;
      const { name: btnname = '', desc = '', verifyType = '' } = this.config.config.property;
      const { apiCode = '' } = this.config.config.data;
      const apiresult = updateDataResult.type === 'error' ? '请求失败' : '请求成功';
      const params = {
        username: name,
        aliasname: aliasName,
        time: new Date().getTime(),
        compid: widgetInstanceId,
        btnname: btnname,
        btndesc: desc,
        secondtype: verifyType,
        apicode: apiCode,
        apiresult: apiresult,
      };
      dataModel[method](rcLogObjModelCode, params).finally(() => {
        if (updateDataResult.type === 'error') {
          this.$message.error('操作失败,请检查！');
        } else {
          this.$message.success('操作成功！');
        }
        this.isLoading = false;
      });
    },
    getTooltip(btn) {
      return {
        config: this.config.config.property.tooltip || {},
        vars: {
          'equipment_id': this.config.config.data.tableData[0]?.value,
          'equipment_status': this.config.config.data.tableData[1]?.value,
        },
        parentComp: this,
      };
    },
    switchControlType(type) {
      this.type = type;
    },

    convertInputType(tableData) {
      // 找到第一个勾选开度值的配置，将value改成当前用户输入的值
      const match = tableData.find(item => item.type === true);
      if (match) {
        match.value = `${this.ratio}`;
        if (this.type === 'speedControl') {
          match.value = `${this.selectVal}`;
        }
      }

      // 将value转换成数据库返回的字段类型，避免可能更新失败
      tableData.forEach(data => {
        const { name, value, dataType } = data;
        if (dataType === 'int' || dataType === 'number' || dataType === 'integer') {
          data.value = parseInt(value) || 0;
        } else if (dataType === 'string' && typeof value !== 'string') {
          data.value = `${value}`;
        } else {
        }
      });
    },

    // 通过xminer的update接口，更新对象模型中的数据
    updateDataByXminer() {
      const { dataSourceType, tableData = [] } = this.config.config.data;
      const [first = {}] = tableData;
      const { id = '' } = first;
      if (id === '') {
        return Promise.reject(requestFailure);
      }

      // 找到第一个勾选开度值的配置，将value改成当前用户输入的值
      const match = tableData.find(item => item.type === true);
      if (match) {
        match.value = `${this.ratio}`;
        if (this.type === 'speedControl') {
          match.value = `${this.selectVal}`;
        }
      }

      // 将value转换成数据库返回的字段类型，避免可能更新失败
      this.convertInputType(tableData);

      // 组合更新字段属性名称和值参数
      const params = {};
      for (const key in tableData) {
        if (tableData[key].code) {
          params[tableData[key].code] = tableData[key].value;
        }
      }

      this.isLoading = true;
      const method = `updateObjModelData${dataSourceType}`;
      return dataModel[method](id, rcEquimentObjModelCode, params);
    },
    updateDataByFabric() {
      const { dataSourceType, tableData = [], apiCode = '' } = this.config.config.data;

      this.convertInputType(tableData);

      const params = { apiCode: apiCode, propertyMapping: {} };
      const values = tableData.map(data => ({ code: data.code, value: data.value }));
      params['params'] = values;
      const method = `getChartData${dataSourceType}`;
      return dataModel[method](params);
    },
    updateData() {
      const { dataSourceType } = this.config.config.data;
      if (dataSourceType === 'xMiner') {
        return this.updateDataByXminer();
      } else if (dataSourceType === 'fabric') {
        return this.updateDataByFabric();
      } else {
        return Promise.reject(requestFailure);
      }
    },
    getStaticData() {
      const data = STATIC_DATA[this.config.propertyPannelName];
      return data;
    },
  },
};
</script>
<style lang="less" scoped>
@bgColor: #0d263a;
@borderColor: #588ba8;
.rc-button {
  position: relative;
  height: 100%;
  .btns {
    display: flex;
    flex-wrap: wrap;
    :deep(.el-input) {
      &.ratio-input {
        .el-input__wrapper {
          background: var(--bgColor);
          box-shadow: none;
          border: 1px solid var(--brColor);
          input::-webkit-inner-spin-button {
            cursor: pointer;
          }
          .el-input__inner {
            color: var(--textColor);
          }
        }
        .el-input-group__append {
          background: var(--bgColor);
          border: 1px solid var(--brColor);
          box-shadow: none;
          border-left: none;
          color: var(--textColor);
        }
      }
    }
    .btn {
      display: flex;
      justify-content: center;
      align-items: center;
      white-space: nowrap;
      cursor: pointer;
      background: #fff;
      color: #606266;
      text-align: center;
      box-sizing: border-box;
      margin: 0;
      font-weight: 500;
      .btn_inner {
        margin: 0;
        padding: 0;
        line-height: 1;
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
    &.flex_start {
      justify-content: flex-start;
    }
    &.flex_end {
      justify-content: flex-end;
    }
    &.flex_center {
      justify-content: center;
    }
    &.flex_space_between {
      justify-content: space-between;
    }
    &.flex_space_around {
      justify-content: space-around;
    }
  }
  .ratio-input {
    width: auto;
    margin-bottom: 10px;
    :deep(input) {
      height: 32px;
      line-height: 32px;
      padding: 5px;
      width: 55px;
      margin: 0px 0px;
    }
    :deep(.el-input-group__append) {
      padding: 0px 5px;
    }
  }
}

.visualComponents_theme_light {
  .rc-button {
    .btn {
      &:hover {
        opacity: 0.8;
      }
    }
  }
}
.select-box-select {
  &.select-box-select-dark {
    :deep(.el-input) {
      .el-input__wrapper {
        background-color: @bgColor;
        border: 1px solid @borderColor;
        box-shadow: none;
      }
      .el-input__inner {
        border-color: #588ba8;
        color: #fff;
        background-color: @bgColor;
      }
      .el-select__icon {
        color: #588ba8;
      }
      .el-input__inner::placeholder {
        color: #cccccc;
      }
    }

    :deep(.el-select__tags) {
      flex-wrap: nowrap;
      overflow: hidden;
    }

    :deep(.select-poper) {
      background-color: @bgColor;
      border-color: #588ba8;

      .el-scrollbar {
        .el-select-dropdown__list {
          .select-box-select-option {
            color: #fff;
            background-color: @bgColor;
            span {
              font-size: 12px;
            }
          }
          .hover {
            background-color: #102e4f;
          }
        }
      }
      .popper__arrow {
        border-bottom-color: #588ba8;

        &::after {
          border-bottom-color: #0d263a;
        }
      }
    }

    :deep(.el-tag--info) {
      background-color: #1f1f1f;
      border-color: #1f1f1f;
      color: #fff;
      .el-tag__close {
        color: #fff;
        background-color: #102e4f;
      }
    }
  }
  &.select-box-select-real {
    :deep(.el-input) {
      .el-input__wrapper {
        background-color: #191919;
        border: 1px solid #5e5e5e;
        box-shadow: none !important;
      }
      .el-select__icon {
        color: #ffffff;
      }
    }
  }
}
.select-poper1-real .el-select-dropdown__item.select-box-select-option-real.el-select-dropdown__item:hover {
  background-color: #102e4f;
}
.select-poper1-dark .el-select-dropdown__item.select-box-select-option-dark.el-select-dropdown__item:hover {
  background-color: #102e4f;
}
.select-poper1-light .el-select-dropdown__item.select-box-select-option-light.el-select-dropdown__item:hover {
  background-color: #e0eeff;
}
.select-box-select-option-real.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
  background-color: #102e4f;
}
.select-box-select-option-dark.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
  background-color: #102e4f;
}
.select-box-select-option-light.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
  background-color: #e0eeff;
}
.select-poper1-real .el-select-dropdown__item {
  color: #ffffff;
}
.select-poper1-dark .el-select-dropdown__item {
  color: #e0eeff;
}
.select-poper1-dark.is-multiple .el-select-dropdown__item.selected {
  background-color: #102e4f;
}
.select-poper1-light.is-multiple .el-select-dropdown__item.selected {
  background-color: #e0eeff;
}
</style>
<style lang="less">
.el-popper.el-select__popper.select-poper1-dark {
  border: 1px solid #588ba8;
  background: #0d263a;
  .el-popper__arrow::before{
    border: 1px solid #588ba8;
    background: #0d263a;
  }
}
.el-popper.el-select__popper.select-poper1-real {
  border: 1px solid #191919;
  background: #191919;
  .el-popper__arrow::before{
    border: 1px solid #191919;
    background: #191919;
  }
}
</style>
